/*
	@file: log/source/LogRunner.cpp
	@author: Wolfhead
 */

#include "LogRunner.h"
#include <vector>
#include <boost/foreach.hpp>

namespace logger
{

LogRunner::LogRunner(const LogOption& option)
	: m_option(option)
	, m_queue(option.queue_buffer) 
{
	set_option(option);
}

void LogRunner::set_option(const LogOption& option)
{
	m_option = option;

	m_queue.set_limit(m_option.queue_buffer);
}

const LogOption& LogRunner::get_option()
{
	return m_option;
}

int LogRunner::start()
{
	if (m_thread_ptr)
	{
		return 0;
	}

	m_running = true;
	boost::shared_ptr<boost::thread> m_thread_ptr(
		new boost::thread(boost::bind(&LogRunner::run, shared_from_this())));

	return 0;
}

int LogRunner::stop()
{
	m_running = false;
	m_queue.notify();
	if (m_thread_ptr)
	{	
		m_thread_ptr->join();
		m_thread_ptr = boost::shared_ptr<boost::thread>();
	}

	return 0;
}

int LogRunner::restart()
{
	stop();
	start();

	return 0;
}

int LogRunner::run()
{
	Queue::QueueType split_queue;
    while (m_running)
    {
        if (0 != m_queue.wait(m_option.queue_timeout))
        {
            continue;
        }

        split_queue.clear();
        m_queue.split(split_queue);

        if (split_queue.empty() || !m_option.logger_ptr)
        {
            continue;
        }
        else
        {
        	std::vector<std::string> message_vec;
        	message_vec.reserve(split_queue.size());

        	BOOST_FOREACH(LogDataPtr data_ptr, split_queue)
        	{
				if (m_option.formatter_ptr && m_option.backend_format)
				{
					std::string message;
					m_option.formatter_ptr->format(data_ptr, message);
					message_vec.push_back(message);
				}        		
        	}

            m_option.logger_ptr->log(message_vec);

            if (m_option.auto_flush)
            {
            	m_option.logger_ptr->flush();
        	}
        }
    }

    return 0;
}

int LogRunner::log(LogDataPtr data_ptr)
{
	if (data_ptr->byname || data_ptr->priority & m_option.priority)
	{			
		m_queue.push(data_ptr);

		if (data_ptr->priority & m_option.force_notify_priority)
		{
			m_queue.notify();
		}
	}

	return 0;
}

}//namespace logger
